#include "Input.h"
#include "Trace.h"

Input::Input(HWND hWnd)
{
	_hWnd = hWnd;

	HRESULT 
		hr = DirectInput8Create
		( 
		GetModuleHandle(NULL),//_hInstance, 
		DIRECTINPUT_VERSION, 
		IID_IDirectInput8, (VOID**)&_di, NULL 
		);

	// TO-DO: put in exception handling
	if (hr!=DI_OK) return;

	trace(L"DirectInput has been created");

	hr = _di->CreateDevice(GUID_SysKeyboard, &_Keyboard, NULL); 

	// TO-DO: put in exception handling
	if (hr!=DI_OK) return;

	trace(L"DirectInput keyboard has been created");

	hr = _Keyboard->SetDataFormat(&c_dfDIKeyboard);

	trace(L"SetDataFormat for keyboard successfully");

	hr = _Keyboard->SetCooperativeLevel(_hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); 

	trace(L"SetCooperativeLevel for keyboard successfully");

	// IMPORTANT STEP TO USE BUFFERED DEVICE DATA!
	//
	// DirectInput uses unbuffered I/O (buffer size = 0) by default.
	// If you want to read buffered data, you need to set a nonzero
	// buffer size.
	//
	// Set the buffer size to DINPUT_BUFFERSIZE (defined above) elements.
	//
	// The buffer size is a DWORD property associated with the device.
	DIPROPDWORD dipdw;

	dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
	dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
	dipdw.diph.dwObj        = 0;
	dipdw.diph.dwHow        = DIPH_DEVICE;
	dipdw.dwData            = KEYBOARD_BUFFER_SIZE; // Arbitary buffer size

	trace(L"SetProperty for keyboard successfully");

	hr = _Keyboard->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph );
	if (hr!=DI_OK) return;

	hr = _Keyboard->Acquire(); 
	if (hr!=DI_OK) return;

	trace(L"Keyboard has been acquired successfully-----------------");

	_Key_Down = 0;
	_Key_Up = 0;
}

Input::~Input()
{
	if( _Keyboard )  
	{
		_Keyboard->Unacquire();
		_Keyboard->Release();
	}

	if (_di) _di->Release();
}


void Input::_InitDirectInput(HWND hWnd)
{
	HRESULT 
		hr = DirectInput8Create
		( 
		GetModuleHandle(NULL),//_hInstance, 
		DIRECTINPUT_VERSION, 
		IID_IDirectInput8, (VOID**)&_di, NULL 
		);

	// TO-DO: put in exception handling
	if (hr!=DI_OK) return;

	trace(L"DirectInput has been created");

	hr = _di->CreateDevice(GUID_SysKeyboard, &_Keyboard, NULL); 

	// TO-DO: put in exception handling
	if (hr!=DI_OK) return;

	trace(L"DirectInput keyboard has been created");
}
void Input::_Init_Keyboard(HWND _hWnd)
{
	HRESULT hr = _Keyboard->SetDataFormat(&c_dfDIKeyboard);

	trace(L"SetDataFormat for keyboard successfully");

	hr = _Keyboard->SetCooperativeLevel(_hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); 

	trace(L"SetCooperativeLevel for keyboard successfully");

	// IMPORTANT STEP TO USE BUFFERED DEVICE DATA!
	//
	// DirectInput uses unbuffered I/O (buffer size = 0) by default.
	// If you want to read buffered data, you need to set a nonzero
	// buffer size.
	//
	// Set the buffer size to DINPUT_BUFFERSIZE (defined above) elements.
	//
	// The buffer size is a DWORD property associated with the device.
	DIPROPDWORD dipdw;

	dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
	dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
	dipdw.diph.dwObj        = 0;
	dipdw.diph.dwHow        = DIPH_DEVICE;
	dipdw.dwData            = KEYBOARD_BUFFER_SIZE; // Arbitary buffer size

	trace(L"SetProperty for keyboard successfully");

	hr = _Keyboard->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph );
	if (hr!=DI_OK) return;

	hr = _Keyboard->Acquire(); 
	if (hr!=DI_OK) return;

	trace(L"Keyboard has been acquired successfully-----------------");

	_Key_Down = 0;
	_Key_Up = 0;
}

void Input::_ReadKeyBoard()
{
	HRESULT result;


	// Read the keyboard device.
	result = _Keyboard->GetDeviceState(sizeof(_KeyStates), (LPVOID)&_KeyStates);
	if(FAILED(result))
	{
		// If the keyboard lost focus or was not acquired then try to get control back.
		if((result == DIERR_INPUTLOST) || (result == DIERR_NOTACQUIRED))
		{
			_Keyboard->Acquire();
		}
		
	}
}
void Input::_Process_KeyBoard()
{
	_Keyboard->Poll();

	// Collect all key states first
	_Keyboard->GetDeviceState( sizeof(_KeyStates), _KeyStates);



	// Collect all buffered events
	DWORD dwElements = KEYBOARD_BUFFER_SIZE;
	HRESULT hr = _Keyboard->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), _KeyEvents, &dwElements, 0 );

	// Scan through all data, check if the key is pressed or released
	for( DWORD i = 0; i < dwElements; i++ ) 
	{
		int KeyCode = _KeyEvents[i].dwOfs;
		int KeyState = _KeyEvents[i].dwData;
		if ( (KeyState & 0x80) > 0)
			_Key_Down = KeyCode;//OnKeyDown(KeyCode);
		else 
			_Key_Up = KeyCode;//OnKeyUp(KeyCode);
	}
}

int Input::IsKeyDown(int KeyCode)
{
	return (_KeyStates[KeyCode] & 0x80) > 0;
}
int Input::GetKeyDown()
{

	//return _Key_Down;

	int temp = _Key_Down;
	_Key_Down = 0;
	return temp;

}
int Input::GetKeyUp()
{
	int temp = _Key_Up;
	_Key_Up = 0;
	return temp;
}



